/** @format */

import { isUrl } from './utils'
import { Toast, Dialog, Notify } from 'vant'
import { getAccessToken } from './userAuth'
// import store from '../store/store'
import { api } from './config'
import { stringify } from 'qs'
import Router from '@/router/router'

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（登录过期、token错误）',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。'
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  }

  // const url = new URL(response.url);
  const errorText = codeMessage[response.status] || response.statusText
  Toast.fail({
    message: errorText
  })

  const error = new Error(errorText)
  error.name = response.status
  error.response = response
  throw error
}

async function checkResponseCode(response) {
  const responseResult =
    response.status === 204 ? await response.text() : await response.json()

  // code: wb.[*].shbaoyuantech.com;  status: byhr.[*].shbaoyua·ntech.com
  if (!('code' in responseResult) && !('status' in responseResult))
    return responseResult

  if (responseResult.code === '0') {
    return responseResult.data
  }

  if (responseResult.code != '0') {
    Toast.fail({
      message: responseResult.message
    })
    return
  }

  // const notifyType = responseResult.status && responseResult.status !== -1 ? 'warning' : 'error';
  const url = new URL(response.url)
  const errorText = responseResult.message || responseResult.error || '未知异常'

  Toast.fail({
    // message: `请求错误 ${responseResult.status || ''}: ${url.pathname}`,
    message: errorText
  })
  const error = new Error(errorText)
  error.name = responseResult.status
  error.response = responseResult
  throw error
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
function request(url, options = {}) {
  const baseURI = isUrl(url) ? '' : api
  const accessToken = getAccessToken()

  const defaultOptions = {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${btoa(accessToken)}`
    },
    formData: false
  }
  const newOptions = {
    ...defaultOptions,
    ...options,
    method: options.method
      ? options.method.toUpperCase()
      : defaultOptions.method,
    body: typeof options.body !== 'undefined' ? options.body : options.data
  }

  if (newOptions.method === 'POST' || newOptions.method === 'PUT') {
    // 对于POST formData 传参 Content-Type使用 application/x-www-form-urlencoded
    // 如果 multipart/form-data wb后端不支持?
    if (newOptions.formData) {
      newOptions.headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        ...newOptions.headers
      }
      newOptions.body = stringify(newOptions.body)
    } else if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        ...newOptions.headers
      }
      if (newOptions.headers['Content-Type'] !== 'application/octet-stream') {
        newOptions.body = JSON.stringify(newOptions.body)
      }
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        Accept: 'application/json',
        ...newOptions.headers
      }
    }
  } else if (newOptions.method === 'GET' || newOptions.method === 'DELETE') {
    /* eslint-disable-next-line no-param-reassign */
    url += newOptions.body ? `?${stringify(newOptions.body)}` : ''

    delete newOptions.body // 避免有些浏览器不兼容
  }

  delete newOptions.formData
  delete newOptions.data
  return fetch(`${baseURI}${url}`, newOptions)
    .then(checkStatus)
    .then(checkResponseCode)
    .catch(e => {
      const status = e.name

      if (status === 401) {
        console.log(Router)
        Router.push('/logout')
        return
      }
      if (status === 403) {
        return
      }
      if (status <= 504 && status >= 500) {
        return
      }
      if (status >= 404 && status < 422) {
        return
      }
    })
}

request.post = (url, body, formData = false) => {
  // const bodyData = formData ? json2formData(body) : body;
  return request(url, { method: 'POST', body, formData })
}

export default request
